//\file: Vector3.cc

#include"Vector3.h"
#include <trax.hpp>

namespace AtomTrace{

/**
const Vector3 Vector3::ZERO(0.0f, 0.0f, 0.0f);
const Vector3 Vector3::UNIT_X(1.0f, 0.0f, 0.0f);
const Vector3 Vector3::UNIT_Y(0.0f, 1.0f, 0.0f);
const Vector3 Vector3::UNIT_Z(0.0f, 0.0f, 1.0f);
**/

Vector3::Vector3():
	_x(0.0f),
	_y(0.0f),
	_z(0.0f)
{}

Vector3::Vector3(float ix, float iy, float iz):
	_x(ix),
	_y(iy),
	_z(iz)
{}

Vector3::Vector3(const Vector3 & other):
	_x(other._x),
	_y(other._y),
	_z(other._z)
{}

Vector3::Vector3(int address)
{
    _x = loadf(address, 0);
    _y = loadf(address, 1);
    _z = loadf(address, 2);
}

void Vector3::Set(float ix, float iy, float iz)
{
    _x = ix;
    _y = iy;
    _z = iz;
}

const float & Vector3::operator[](int index) const
{
	return *((&_x)+index);
}

float & Vector3::operator[](int index)
{
	return *((&_x)+index);
}

const Vector3 & Vector3::operator=(const Vector3 & rhs)
{
	_x = rhs._x;
	_y = rhs._y;
	_z = rhs._z;

	return *this;
}

const Vector3 Vector3::operator+(const Vector3 & rhs) const
{
	return Vector3(_x+rhs._x, _y+rhs._y, _z+rhs._z);
}

const Vector3 Vector3::operator-(const Vector3 & rhs) const
{
	return Vector3(_x-rhs._x, _y-rhs._y, _z-rhs._z);
}

const Vector3 Vector3::operator*(float rhs) const //scale
{
	// should detect if rhs is nan in C++
	return Vector3(_x*rhs, _y*rhs, _z*rhs);
}

const Vector3 Vector3::operator/(float rhs) const //scale
{
	//assert(!isNAN(rhs));
	//assert(rhs >= 0.000001f || rhs <= -0.000001f);
	return Vector3(_x/rhs, _y/rhs, _z/rhs);
}

const float Vector3::Dot(const Vector3 & rhs) const
{
	return (_x*rhs._x + _y*rhs._y + _z*rhs._z);
}

const Vector3 Vector3::Cross(const Vector3 & rhs) const
{
	Vector3 resVec( _y * rhs._z - _z * rhs._y,
					_z * rhs._x - _x * rhs._z,
					_x * rhs._y - _y * rhs._x);
	return resVec;
}


const Vector3 Vector3::GetNormalize(void) const
{
	float fac = invsqrt(_x*_x + _y*_y + _z*_z);
	return Vector3(_x*fac, _y*fac, _z*fac);
}

void Vector3::Normalize(void)
{
	float fac = invsqrt(_x*_x + _y*_y + _z*_z);
	//assert(fac > 0.0001f);
	_x *= fac;
	_y *= fac;
	_z *= fac;
}

const float Vector3::Length() const
{
	return sqrt(_x*_x + _y*_y + _z*_z);
}

const float Vector3::LengthSquare() const
{
	return (_x*_x + _y*_y + _z*_z);
}

} // namespace AtomTrace


